#include "wmi_connection.h"

using namespace std;
using namespace log4cxx;
using namespace log4cxx::xml;
using namespace log4cxx::helpers;

WMI_HResult 
WMI_Connection::executeQuery(const wchar_t* wql_query)
{
	DOMConfigurator::configure("LogConfig.xml");
	HRESULT hres;
	LoggerPtr loggerWConn(Logger::getLogger("loggerWConn"));
	stringstream out;
    WMI_HResult whres;

	hres = _pSvc->ExecQuery(
		bstr_t(WQL.c_str()), 
        bstr_t(wql_query),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
        NULL,
        &_pEnumerator);
	
    if (FAILED(hres))
    {
        whres.setDescription(QUERY_FAILED);
        whres.setHRESULT(hres);
        LOG4CXX_ERROR(loggerWConn, whres.toString());
        close();        
		CoUninitialize();
        return whres;               // Program has failed.
    }

	COAUTHIDENTITY authIdent;

    memset(&authIdent, 0, sizeof(COAUTHIDENTITY));
	authIdent.PasswordLength = wcslen (password.c_str());
	authIdent.Password = (USHORT*)password.c_str();        
	authIdent.User = (USHORT*)user.c_str();
	authIdent.UserLength = wcslen(user.c_str());

	authIdent.Domain = (USHORT*)domain.c_str();
	authIdent.DomainLength = wcslen(domain.c_str());
    authIdent.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;	
	
    hres = CoSetProxyBlanket(
        _pEnumerator,                    // Indicates the proxy to set
        RPC_C_AUTHN_DEFAULT,            // RPC_C_AUTHN_xxx
        RPC_C_AUTHZ_DEFAULT,            // RPC_C_AUTHZ_xxx
        COLE_DEFAULT_PRINCIPAL,         // Server principal name 
        RPC_C_AUTHN_LEVEL_PKT_PRIVACY,  // RPC_C_AUTHN_LEVEL_xxx 
        RPC_C_IMP_LEVEL_IMPERSONATE,    // RPC_C_IMP_LEVEL_xxx
        &authIdent,                       // client identity
        EOAC_NONE                       // proxy capabilities 
	);

    if (FAILED(hres))
    {
        whres.setDescription(PROXY_NOT_SET);
        whres.setHRESULT(hres);
		LOG4CXX_ERROR(loggerWConn, whres.toString());
		close();
        return whres;               // Program has failed.
    }

	return whres;
}

WMI_HResult 
WMI_Connection::getClassObject(const wchar_t* className,IWbemClassObject** classObject)
{
	DOMConfigurator::configure("LogConfig.xml");
	HRESULT hres;	
	LoggerPtr loggerWConn(Logger::getLogger("loggerWConn"));
	stringstream out;
    WMI_HResult whres;

	BSTR Name =(BSTR) className;
	hres = _pSvc->GetObject(Name, 0, NULL, classObject, NULL);
	
    if (FAILED(hres))
    {
        whres.setDescription(QUERY_FAILED);
        whres.setHRESULT(hres);
        LOG4CXX_ERROR(loggerWConn, whres.toString());
        _pSvc->Release();
		CoUninitialize();
        return whres;               // Program has failed.
    }

	return whres;
}

void 
WMI_Connection::close()
{	
	if (_pEnumerator != NULL)
    {
		_pEnumerator->Release();
    }

	CoUninitialize();
}

void 
WMI_Connection::setUser(wstring u)
{
	user = u;
}

void
WMI_Connection::setPassword(wstring pass)
{
	password = pass;
}

void
WMI_Connection::setDomain(wstring dom)
{
	domain = dom;
}